#pragma once 

#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>


#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_run
{
  using namespace ns_log;
  using namespace ns_util;

  class Run
  {
      
     static void SetCpuMemLimit(int cpu_size,int mem_size)
     {
        struct rlimit cpu;
        cpu.rlim_max=RLIM_INFINITY;

        cpu.rlim_cur=cpu_size;
        setrlimit(RLIMIT_CPU,&cpu);

        struct rlimit mem;
        mem.rlim_max=RLIM_INFINITY;

        mem.rlim_cur=mem_size*10240;
        setrlimit(RLIMIT_AS,&mem);
     }
    public:
      Run(){}
      ~Run(){}

      static int run(const std::string& filename,int cpu_size,int mem_size)
      {
        std::string runname=PathUtil::exe(filename);
        std::string runstdcin=PathUtil::stdcin(filename);
        std::string runstdcout=PathUtil::stdcout(filename);
        std::string runstderror=PathUtil::stderror(filename);
        
        umask(0);
        int stdcin=open(runstdcin.c_str(),O_CREAT|O_RDONLY,0644);
        int stdcout=open(runstdcout.c_str(),O_CREAT|O_WRONLY,0644);
        int stderror=open(runstderror.c_str(),O_CREAT|O_WRONLY,0644);
        if(stdcin<0||stdcout<0||stderror<0)
        {
          LOG(ERROR)<<"打开各种文件失败"<<std::endl;
          return -3;
        }
        
        std::cout<<runname<<std::endl;
        pid_t pid=fork();
        if(pid<0)
        {
          close(stdcin);
          close(stdcout);
          close(stderror);
          LOG(ERROR)<<"创建进程失败"<<std::endl;
          return -1;
        }
        else if(pid==0)
        {
          dup2(stdcin,0);
          dup2(stdcout,1);
          dup2(stderror,2);
          
          SetCpuMemLimit(cpu_size,mem_size);

          execl(runname.c_str(),runname.c_str(),nullptr);
          exit(1);
        }
        else 
        {
          close(stdcin);
          close(stdcout);
          close(stderror);
          int status=0;
          waitpid(pid,&status,0);
          LOG(INFO)<<"运行成功"<<(status&0x7f)<<std::endl;
          return status&0x7f;
        }
      }
  };
}

